﻿using System;

using OCXS;
using OCXS.OCXSServiceLibrary.OPCXMLDA10;

namespace OCXS {

	namespace OCXSServiceLibrary {
        
		public partial class OCXSService {

			/// <summary>
            /// <para>
            /// Implements OPC XML DA 1.0 SubscriptionCancel service. 
            /// </para>
            /// <para>
            /// See OPC XML DA 1.0 specification for more information about SubscriptionCancel service.
            /// </para>
            /// </summary>
            /// <remarks>
            /// <para>
            ///     <b>Following there's a list of implemented (or not) standard features.</b>
            /// </para>
            /// <para>
            ///     The following <c>SubscriptionCancelRequest</c> standard features are (or not) implemented.
            /// 
            ///     <ul>
            ///         <li><b>ClientRequestHandle: </b> supported.</li>
            ///         <li><b>ServerSubHandle: </b> supported.</li>
            ///     </ul>
            /// </para>
            /// 
            /// <para>
            ///     The following <c>SubscriptionCancelResponse</c> standard features are (or not) implemented.
            ///     <ul>
            ///         <li><b>ClientRequestHandle: </b> supported.</li>
            ///     </ul>
            /// </para>
            /// 
            /// <para>
            /// <b>Subscription Garbage Collection:</b><br />
            /// OCXS Server keeps an internal Garbage Collector for all Subscriptions in the 
            /// <see cref="OCXS.OCXSServiceLibrary.OCXSService.subscriptionTable"/>.<br />
            /// When the <c>SubscriptionCancel</c> is called, the corresponding Subscription specified in the 
            /// request, is disposed. Disposal means the Subscription physical and computational resources are
            /// freed; however the table will still keep the subscription record (marked as disposed).<br />
            /// The <c>SubscriptionRecord</c> will be removed from the 
            /// <see cref="OCXS.OCXSServiceLibrary.OCXSService.subscriptionTable"/> on the immediate Garbage
            /// Collection Cycle (collection rate specified in the 
            /// <see cref="OCXS.OCXSServiceLibrary.OCXSService.SubscriptionCollectionPeriod"/> constant).
            /// </para>
            /// 
            /// <code>
            /// // The following code can be found in OCXSClient and 
            /// // shows how to call SubscriptionCancel service.
            /// class Program {
            ///
            ///     private const string EndpointAddress = "http://localhost/OCXS/OCXS.svc";
            ///     
            ///     static void Main(string[] args) {
            ///     
            ///     // In the response subscribed Item values will be returned.
            ///     // The subscription expires after 10 seconds of inactivity.
            ///     SubscribeResponse sr = Subscribe("en-us", "0x00FF", true, 10000);
            ///     
            ///     // Call SubscriptionPolledRefresh on subscription previously initialized.
            ///     // This is an Advanced Polled Refresh, since we provide a valid Hold Time
            ///     // (10 seconds after actual time).
            ///     SubscriptionPolledRefreshResponse sprr = SubscriptionPolledRefresh(
            ///         "en-us",
            ///         "0x0100",
            ///         new string[1] { sr.ServerSubHandle },
            ///         DateTime.Now + new TimeSpan(0, 0, 10),
            ///         5000,
            ///         false);
            ///         
            ///     // Cancel subscription.
            ///     SubscriptionCancel(sr.ServerSubHandle, "0x0101");
            /// }
            /// 
            /// public static SubscriptionCancelResponse SubscriptionCancel(string sid, string clientRequestHandle)
            /// {
            /// 	// Get the channel.
            /// 	// GetOCXSChannel can be found in OCXSClient.
            /// 	IOCXSService svc = GetOCXSChannel(EndpointAddress);
            /// 
            /// 	// This request needs just the Subscription identifier (`sid`) and a handle to
            /// 	// identify the request in the system.
            /// 	SubscriptionCancelRequest SCR = new SubscriptionCancelRequest(sid, clientRequestHandle);
            /// 
            ///     // Perform the call to service and get the response.
            /// 	SubscriptionCancelResponse res = svc.SubscriptionCancel(SCR);
            /// 
            ///     // Print the response.
            ///     // PrintResponse can be found in OCXSClient.
            /// 	PrintResponse(res);
            /// 
            /// 	return res;
            /// }
            /// </code>
            /// 
            /// </remarks>
            /// <param name="request">The <c>SubscriptionCancelRequest</c> issued by client according to OCP XML DA 1.0 specification.</param>
            /// <returns>A <c>SubscriptionCancelResponse</c> according to OPC XML DA 1.0 specification.</returns>
			public SubscriptionCancelResponse SubscriptionCancel(SubscriptionCancelRequest request) {

                SubscriptionCancelResponse SCR = new SubscriptionCancelResponse(request.ClientRequestHandle);

                // Deallocating
                SubscriptionRecord sr = null;

                lock (this.subscriptionTablePadlock) {
                    if (this.subscriptionTable.TryGetValue(request.ServerSubHandle, out sr)) {             
                        // Note: Disposing entry for deletion. 
                        //       Record in table will be removed by collector.
                        sr.Dispose();
                    }
                }

                SCR.ClientRequestHandle = request.ClientRequestHandle;

                return SCR;

			}

		}
        
	}

}
